#!/usr/bin/env python

import random
import numpy as np
from math import factorial

class node(object):
	def __init__(self, ID):
		self.has_packet = False
		self.received_packets = 0
		self.id = ID
	
	def receive_packet(self, succesrate):
		if random.random() <= succesrate:
			self.has_packet = True
			self.received_packets = self.received_packets + 1
			
	def reset(self):
		self.has_packet = False
		self.received_packets = 0

def nc_probability(total_transmissions, needed_packets, succesrate):
	if total_transmissions < needed_packets:
		return 0
	else:
		return (factorial(total_transmissions) / factorial(total_transmissions - needed_packets) / factorial(needed_packets) * (succesrate**needed_packets) * ((1 - succesrate)**(total_transmissions - needed_packets)) )

def nc_probability_after_extra_transmissions(needed, total_transmissions, succesrate):
	extra_transmissions = total_transmissions - needed
	node_rate = 0
	for trans in range(extra_transmissions+1):
		node_rate = node_rate + nc_probability(total_transmissions, needed+trans,succesrate)
	return node_rate


if __name__=='__main__':
	### Setup HERE!!: ###
	packets_needed = 100
	extra_transmissions = 28
	node_count = 100
	succesrate = 0.9
	### /Setup ###

	print '\nCalculations:'

	#for trans in range(extra_transmissions+1):
	#	node_rate = node_rate + nc_probability(total_transmissions, packets_needed+trans,succesrate)
	node_rate = nc_probability_after_extra_transmissions(packets_needed, packets_needed+extra_transmissions, succesrate)

	print 'Probability of all nodes receiving',packets_needed,'when sending',packets_needed+extra_transmissions,'linearly independant packets:',node_rate**node_count


	total_transmissions = packets_needed + extra_transmissions
	nodes = []
	reps = 10000
	print
	print 'Starting simulation with stats:'
	print 'devices =',node_count
	print 'succesrate =',succesrate
	print 'transmissions =',total_transmissions
	print 'packets needed =', packets_needed
	print 'reps =',reps


	fail = 0


	for i in range(node_count):
		nodes.append(node(i))

	print '\nSimulation running..'

	for rep in range(reps):
		for trans in range(total_transmissions):
			for node in nodes:
				node.receive_packet(succesrate)
			
		for node in nodes:
			if node.received_packets < packets_needed:
				fail = fail + 1
				break
			
		for node in nodes:
			node.reset()
	
		
	print 'Not all nodes received the needed packets: '+str(packets_needed)+', in',fail,'out of',reps,'cycles. Succes rate:',(reps-fail)/float(reps)
	print
	print	
		
	
